﻿#include "Relation.h"
#include "Cache/OfflineCharacterData.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "RelationMgr.h"
#include <algorithm>

//RelationPlayer::RelationPlayer()
//{
//	id = 0;
//	/*lastGivePlyTime = 0;
//	getPlyStatus = 0;
//	lastGetPhyTime = 0;*/
//}

void RelationTeam::AddUser(CharIDType userID)
{
	RelationPlayer p;
	p.id = userID;
	/*p.lastGivePlyTime = 0;*/
	
	playerList.push_back(p);
}

void RelationTeam::AddUser(RelationPlayer user)
{
	playerList.push_back(user);
}

void RelationTeam::AddUser(const RelationMember& memberData)
{
	RelationPlayer p;
	p.id = memberData.id();
	p.closeness = memberData.closeness();
	p.closenessLv = memberData.closenesslv();
	p.passDuplicateClonseness = memberData.passduplicatecloseness();
	p.killMonsterClonseness = memberData.killmonstercloseness();
	p.handselRoseClonseness = memberData.handselrosecloseness();
	p.updateTime = memberData.updatetime();
	p.killMeTimes = memberData.hate();

	playerList.push_back(p);
}

void RelationTeam::DelUser(CharIDType userID)
{
	for (PlayerList::iterator it = playerList.begin(); it != playerList.end();)
	{
		if ((*it).id == userID)
		{
			it = playerList.erase(it);
			return;
		}
		else
		{
			++it;
		}
	}
}

uint32_t RelationTeam::GetNum()
{
	return playerList.size();
}

bool RelationTeam::HaveUser(CharIDType userID)
{
	for (PlayerListIter it = playerList.begin(); it != playerList.end(); ++it)
	{
		if ((*it).id == userID)
		{
			return true;
		}
	}
	
	return false;
}

void RelationTeam::LoadMember(const RelationMember& memberData)
{
	CharIDType id = memberData.id();
	if (HaveUser(id))
	{
		return;
	}

	AddUser(memberData);
}

void RelationTeam::SaveMember(::google::protobuf::RepeatedPtrField< ::ProtoBuf::RelationMember >* memberData)
{
	PlayerListIter iter = playerList.begin();
	for (; iter != playerList.end(); ++iter)
	{
		RelationMember* pRelationMember = memberData->Add();
		pRelationMember->set_id(iter->id);
		pRelationMember->set_closeness(iter->closeness);
		pRelationMember->set_closenesslv(iter->closenessLv);
		pRelationMember->set_passduplicatecloseness(iter->passDuplicateClonseness);
		pRelationMember->set_killmonstercloseness(iter->killMonsterClonseness);
		pRelationMember->set_handselrosecloseness(iter->handselRoseClonseness);
		pRelationMember->set_updatetime(iter->updateTime);
		pRelationMember->set_hate(iter->killMeTimes);
	}	
}

RelationPlayer* RelationTeam::GetUser(CharIDType userID)
{
	for (PlayerListIter it = playerList.begin(); it != playerList.end(); ++it)
	{
		if ((*it).id == userID)
		{
			return &(*it);
		}
	}

	return nullptr;
}

bool RelationTeam::AddHate(CharIDType userID)
{
	RelationPlayer* pRelationPlayer = GetUser(userID);
	if (nullptr == pRelationPlayer)
	{
		if (playerList.size() >= MAX_HATE_SIZE)
		{
			playerList.pop_front();
		}

		RelationPlayer p;
		p.id = userID;
		p.killMeTimes = 1;
		playerList.push_back(p);
		return true;
	}

	pRelationPlayer->killMeTimes++;

	return true;
}

Relation::Relation()
{
	CleanUp();
}

Relation::~Relation()
{
	CleanUp();
}

void Relation::CleanUp()
{
	_groupList.clear();
	_groupList.resize(MAX_GROUP);

	_recentList.clear();
	_friendMap.clear();
	_applyList.clear();
	_friendPhysicalTabMap.clear();
	_friendGetPhysicalTabMap.clear();
	_lastGivePlyTime = 0;
	_giveTimes = 0;
	_progress = 0;
	_cdTime = 0;
	_charmToday = 0;
	_charmWeek = 0;
	_charmLstWeek = 0;
	_friendsAdd = 0;
	_active = 0;
	_change = false;
}

void Relation::LoadData(const RelationDBInfo &data)
{
	//加载分组数据
	for (int i = 0; i < data.info_size(); i++)
	{
		uint32_t gourpIndex = data.info(i).groupindex();
		_groupList[gourpIndex].playerList.clear();

		for (int j = 0; j < data.info(i).members_size(); j++)
		{
			CharIDType id = data.info(i).members(j).id();
			_groupList[gourpIndex].LoadMember(data.info(i).members(j));

			if (gourpIndex == GROUP_FRIEND) //如果是好友
			{
				_friendMap[id] = gourpIndex;
			}
		}
	}

	//加载赠送过体力数据
	uint64_t now = Time::Now().UnixSec();
	for (int i = 0; i < data.physicaltab_size(); i++)
	{
		const RelationPhysicalTab& physicalTab = data.physicaltab(i);
		CharIDType id = physicalTab.id();

		//如果该玩家已经没有在自己的好友列表中了,判断是否要移除体力标记
		if (nullptr == _groupList[GROUP_FRIEND].GetUser(id))
		{
			uint64_t lastGivePlyTime = physicalTab.lastgiveplytime();
			//如果已经不是同一天了直接移除
			if (Time::GetLocalDayDifference(lastGivePlyTime, now) != 0)
			{
				continue;
			}
		}

		FriendPhysicalTab tab;
		tab.getPlyStatus = physicalTab.getplystatus();
		tab.lastGetPhyTime = physicalTab.lastgetphytime();
		tab.lastGivePlyTime = physicalTab.lastgiveplytime();
		_friendPhysicalTabMap[id] = tab;
	}

	//加载好友领取体力数据
	for (int i = 0; i < data.getphysicaltab_size(); i++)
	{
		const RelationGetPhysicalTab& physicalTab = data.getphysicaltab(i);
		CharIDType id = physicalTab.id();
		FriendGetPhysicalTab tab;
		tab.getPlyTime = physicalTab.getplytime();
		_friendGetPhysicalTabMap[id] = tab;
	}

	for (int i = 0; i < data.applylist_size(); i++)
	{
		_applyList.push_back(data.applylist(i));
	}

	_giveTimes = data.givetimes();
	_lastGivePlyTime = data.lastgiveplytime();
	_progress = data.progress();
	_friendsAdd = data.friends_add();
}

bool Relation::SaveDate(RelationDBInfo& saveData)
{
	if (!_change)
	{
		return false;
	}

	for (uint32_t i = 0; i < _groupList.size(); i++)
	{
		RelationInfo* pInfo = saveData.add_info();
		pInfo->set_groupindex(i);
		_groupList[i].SaveMember(pInfo->mutable_members());

	}

	uint64_t now = Time::Now().UnixSec();
	//保存赠送过体力数据
	FriendPhysicalTabIter iter = _friendPhysicalTabMap.begin();
	for (; iter != _friendPhysicalTabMap.end(); ++iter)
	{
		//如果该玩家已经没有在自己的好友列表中了,判断是否要移除体力标记
		if (nullptr == _groupList[GROUP_FRIEND].GetUser(iter->first))
		{
			uint64_t lastGivePlyTime = iter->second.lastGivePlyTime;
			//如果已经不是同一天了直接移除
			if (Time::GetLocalDayDifference(lastGivePlyTime, now) != 0)
			{
				continue;
			}
		}

		RelationPhysicalTab* physicalTab = saveData.add_physicaltab();
		physicalTab->set_id(iter->first);
		physicalTab->set_getplystatus(iter->second.getPlyStatus);
		physicalTab->set_lastgetphytime(iter->second.lastGetPhyTime);
		physicalTab->set_lastgiveplytime(iter->second.lastGivePlyTime);
	}

	//保存好友领取过的体力数据
	FriendGetPhysicalTabIter getIter = _friendGetPhysicalTabMap.begin();
	for (; getIter != _friendGetPhysicalTabMap.end(); ++getIter)
	{
		RelationGetPhysicalTab *physicalTab = saveData.add_getphysicaltab();
		physicalTab->set_id(getIter->first);
		physicalTab->set_getplytime(getIter->second.getPlyTime);
	}

	for (Relation::ApplyIDListpIter iter = _applyList.begin(); iter != _applyList.end(); ++iter)
	{
		saveData.add_applylist(*iter);
	}

	saveData.set_givetimes(_giveTimes);
	saveData.set_lastgiveplytime(_lastGivePlyTime);
	saveData.set_progress(_progress);
	saveData.set_friends_add(_friendsAdd);
	_change = false;
	return true;
}

bool Relation::HaveApply(CharIDType playerID)
{
	ApplyIDListpIter iter = _applyList.begin();
	for (; iter != _applyList.end(); ++iter)
	{
		if (*iter == playerID)
		{
			return true;
		}
	}

	return false;
}

void Relation::DeleteApply(CharIDType playerID)
{
	ApplyIDListpIter iter = _applyList.begin();
	for (; iter != _applyList.end(); )
	{
		if (*iter == playerID)
		{
			iter = _applyList.erase(iter);
			_change = true;
			return;
		}
		else
		{
			++iter;
		}
	}
}

void Relation::ClearApply()
{
	_applyList.clear();
	_change = true;
}

bool Relation::AddApply(CharIDType playerID)
{
	if (HaveApply(playerID))
	{
		return false;
	}

	uint32_t size = _applyList.size();
	if (size >= MAX_APPLY_SIZE)
	{
		//移除掉链头第一个元素
		_applyList.pop_front();
	}

	_applyList.push_back(playerID);
	_change = true;
	return true;
}

bool Relation::IsIndexLegal(uint32_t index)
{
	if ((index >= 0) && (index <= MAX_GROUP_INDEX))
	{
		return true;
	}
	return false;
}

bool Relation::AddUser(uint32_t index, CharIDType playerID)
{
	//是否是有效的组
	if (IsIndexLegal(index) == false)
	{
		return false;
	}

	//如果是黑名单
	if (index == GROUP_BLACK)
	{
		_groupList[index].AddUser(playerID);
		//给黑名单管理器增加角色
		_change = true;
		return true;
	}

	//如果是仇恨列表
	if (index == GROUP_HATE)
	{
		_groupList[index].AddHate(playerID);
		_change = true;
		return true;
	}

	_groupList[index].AddUser(playerID);
	_friendMap[playerID] = index;
	_change = true;
	return true;
}

uint32_t Relation::GetFriendGroupIndex(CharIDType playerID)
{
	IDMapIter iter = _friendMap.find(playerID);
	if (iter == _friendMap.end())
	{
		return GROUP_ERROR;
	}

	return iter->second;
}

bool Relation::DelUser(uint32_t index, CharIDType playerID)
{
	if (IsIndexLegal(index) == false)
	{
		return false;
	}

	if (index == GROUP_FRIEND) //如果是好友
	{
		IDMapIter iter = _friendMap.find(playerID);
		if (iter != _friendMap.end())
		{
			_friendMap.erase(iter);
		}
	}

	if (index == GROUP_BLACK) //如果是黑名单
	{

	}

	_groupList[index].DelUser(playerID);
	_change = true;
	return true;
}

bool Relation::IsMyfriend(CharIDType playerID)
{
	IDMapIter iter = _friendMap.find(playerID);
	if (iter == _friendMap.end())
	{
		return false;
	}

	return true;
}

bool Relation::FriendNumLimit()
{
	if (_friendMap.size() >= MAX_FRIEND_SIZE)
	{
		return true;
	}

	return false;
}

bool Relation::BlackNumLimit()
{
	RelationTeam groupList = _groupList[GROUP_BLACK];
	uint32_t num = groupList.GetNum();
	if (num >= MAX_BLACK_SIZE)
	{
		return true;
	}

	return false;
}

bool Relation::inBlack(CharIDType playerID)
{
	RelationTeam groupList = _groupList[GROUP_BLACK];
	return groupList.HaveUser(playerID);
}

Relation::RecentList& Relation::GetRecentList()
{
	return _recentList;
}

bool Relation::InRecentList(CharIDType playerID)
{
	RecentListIter iter = _recentList.begin();
	for (; iter != _recentList.end(); ++iter)
	{
		if (iter->id == playerID)
		{
			return true;
		}
	}

	return false;
}

void Relation::UpdateRecentList(CharIDType playerID, uint32_t type)
{
	//如果在黑名单 则不添加到联系人
	if (inBlack(playerID))
	{
		return;
	}

	//删除掉该玩家有的关系类型
	DeleteRecentList(playerID);

	uint32_t size = _recentList.size();
	if (size >= MAX_RECENT_SIZE)
	{
		//移除掉链头第一个元素
		_recentList.pop_front();
	}

	RecentPlayer player;
	player.id = playerID;
	player.recentType = type;
	player.recentTime = Time::Now().UnixSec();
	_recentList.push_back(player);
	//_change = true;
}

void Relation::DeleteRecentList(CharIDType playerID)
{
	RecentListIter iter = _recentList.begin();
	for (; iter != _recentList.end();)
	{
		if (iter->id == playerID)
		{
			iter = _recentList.erase(iter);
			return;
		}
		else
		{
			++iter;
		}
	}
}

Relation::GroupList& Relation::GetGroupList()
{
	return _groupList;
}

uint32_t Relation::GetLeftGiveTimes()
{
	uint64_t nowTime = Time::Now().UnixSec();
	if (Time::GetLocalDayDifference(_lastGivePlyTime, nowTime) != 0 && _giveTimes > 0)
	{
		_giveTimes = 0;
		_lastGivePlyTime = nowTime;
		_change = true;
		return MAX_GIVE_PHY_TIMES;
	}

	return (MAX_GIVE_PHY_TIMES - _giveTimes <= 0 ? 0 : MAX_GIVE_PHY_TIMES - _giveTimes);
}

ProtoBuf::ERetCode Relation::GivePhyscial(CharIDType playerID)
{
	RelationPlayer* pRelationPlayer = _groupList[GROUP_FRIEND].GetUser(playerID);
	if (nullptr == pRelationPlayer)
	{
		MMOLOG_FMT_ERROR("[center] Relation::GivePhyscial but RelationPlayer is nullptr,playerID:%llu ", playerID);
		return RET_RELATION_NOT_FRIENDS;
	}

	//判断今天是否已经赠送过了
	uint64_t nowTime = Time::Now().UnixSec();

	//判断是否有领取体力的标记
	FriendPhysicalTabIter iter = _friendPhysicalTabMap.find(playerID);
	if (iter == _friendPhysicalTabMap.end())
	{
		FriendPhysicalTab tab;
		_friendPhysicalTabMap[playerID] = tab;
	}

	uint64_t giveTime = _friendPhysicalTabMap[playerID].lastGivePlyTime;
	if (Time::GetLocalDayDifference(nowTime, giveTime) == 0)
	{
		return RET_RELATION_HAVE_GIVE_PHYSICAL;
	}

	//判断是否还有赠送次数
	if (GetLeftGiveTimes() <= 0)
	{
		return RET_RELATION_GIVE_PHYSICAL_TIMES_LIMIT;
	}

	//可以赠送的话
	_friendPhysicalTabMap[playerID].lastGivePlyTime = nowTime;
	_giveTimes += 1;
	_change = true;
	_lastGivePlyTime = nowTime;
	return RET_SUCCESS;
}

ProtoBuf::ERetCode Relation::SetGivePhyStatus(CharIDType playerID)
{
	RelationPlayer* pRelationPlayer = _groupList[GROUP_FRIEND].GetUser(playerID);
	if (nullptr == pRelationPlayer)
	{
		MMOLOG_FMT_ERROR("[center] Relation::GivePhyscial but RelationPlayer is nullptr,playerID:%llu ", playerID);
		return RET_RELATION_NOT_FRIENDS;
	}

	//判断是否有领取体力的标记
	FriendPhysicalTabIter iter = _friendPhysicalTabMap.find(playerID);
	if (iter == _friendPhysicalTabMap.end())
	{
		FriendPhysicalTab tab;
		_friendPhysicalTabMap[playerID] = tab;
	}

	_friendPhysicalTabMap[playerID].getPlyStatus = RELATION_PHYSICAL_IN_GIVE;
	_friendPhysicalTabMap[playerID].lastGetPhyTime = Time::Now().UnixSec();
	_change = true;

	return RET_SUCCESS;
}

ProtoBuf::ERetCode Relation::GetPhyscial(CharIDType playerID)
{
	RelationPlayer* pRelationPlayer = _groupList[GROUP_FRIEND].GetUser(playerID);
	if (nullptr == pRelationPlayer)
	{
		MMOLOG_FMT_ERROR("[center] Relation::GetPhyscial but RelationPlayer is nullptr,playerID:%llu ", playerID);
		return RET_RELATION_NOT_FRIENDS;
	}

	FriendPhysicalTabIter iter = _friendPhysicalTabMap.find(playerID);
	if (iter == _friendPhysicalTabMap.end())
	{
		MMOLOG_FMT_ERROR("[center] Relation::GetPhyscial but FriendPhysicalTab is nullptr,playerID:%llu ", playerID);
		return RET_FAIL;
	}

	//判断是否超过了领取时间
	uint64_t nowTime = Time::Now().UnixSec();
	uint64_t getTime = _friendPhysicalTabMap[playerID].lastGetPhyTime;

	if (Time::GetLocalDayDifference(nowTime, getTime) != 0)
	{
		_friendPhysicalTabMap[playerID].getPlyStatus = RELATION_PHYSICAL_NOT_GIVE;
		return RET_RELATION_GET_PHYSICAL_TIME_LIMTI;
	}

	//判断是否可以领取
	if (_friendPhysicalTabMap[playerID].getPlyStatus == RELATION_PHYSICAL_NOT_GIVE)
	{
		return RET_RELATION_NOT_GET_PHYSICAL;
	}

	if (_friendPhysicalTabMap[playerID].getPlyStatus == RELATION_PHYSICAL_HAVE_GIVE)
	{
		return RET_RELATION_HAVE_GET_PHYSICAL;
	}

	_friendPhysicalTabMap[playerID].getPlyStatus = RELATION_PHYSICAL_HAVE_GIVE; //标记已经领取过了

	/*if (_progress >= MAX_GIVE_PHY_TIMES)
	{
		return RET_SUCCESS;
	}

	_progress += 1;*/
	_change = true;

	return RET_SUCCESS;
}

bool Relation::CanGetPhyGift()
{
	if (_progress >= MAX_RETURN_GIVE_PHY_TIMES)
	{
		_progress = 0;
		_change = true;
		return true;
	}

	return false;
}

Relation::ApplyIDList Relation::GetApplyIDList()
{
	return _applyList;
}

uint32_t Relation::GetGiftProgress()
{
	//return _progress;
	return _friendGetPhysicalTabMap.size();
}

void Relation::AddGiftProgress(CharIDType charId)
{
	//if (_progress >= MAX_RETURN_GIVE_PHY_TIMES)
	if (_friendGetPhysicalTabMap.size() >= MAX_RETURN_GIVE_PHY_TIMES)
	{
		return;
	}

	_progress += 1;
	FriendGetPhysicalTab tab;
	tab.getPlyTime = Time::Now().UnixSec();
	_friendGetPhysicalTabMap[charId] = tab;
	_change = true;
}

bool Relation::InCdTime()
{
	uint64_t nowTime = Time::Now().UnixSec();
	if (_cdTime == 0)
	{
		_cdTime = nowTime;
		return false;
	}

	if (nowTime - _cdTime >= RELATION_CD_TIME)
	{
		_cdTime = nowTime;
		return false;
	}

	return true;
}

FriendPhysicalTab* Relation::GetFriendPhysicalTab(CharIDType playerID)
{
	FriendPhysicalTabIter iter = _friendPhysicalTabMap.find(playerID);
	if (iter != _friendPhysicalTabMap.end())
	{
		return &(iter->second);
	}

	return nullptr;
}

void Relation::DelFriendPhysicalTab(CharIDType playerID)
{
	FriendPhysicalTabIter iter = _friendPhysicalTabMap.find(playerID);
	if (iter != _friendPhysicalTabMap.end())
	{
		_friendPhysicalTabMap.erase(iter);
		_change = true;
	}
}

FriendGetPhysicalTab* Relation::GetFriendGetPhysicalTab(CharIDType playerID)
{
	FriendGetPhysicalTabIter iter = _friendGetPhysicalTabMap.find(playerID);
	if (iter != _friendGetPhysicalTabMap.end())
	{
		return &(iter->second);
	}

	return nullptr;
}

void Relation::DelFriendGetPhysicalTab(CharIDType playerID)
{
	FriendGetPhysicalTabIter iter = _friendGetPhysicalTabMap.find(playerID);
	if (iter != _friendGetPhysicalTabMap.end())
	{
		_friendGetPhysicalTabMap.erase(iter);
		_change = true;
	}
}

Relation::IDMap& Relation::GetFriendMap()
{
	return _friendMap;
}

void Relation::DeleteRelation(CharIDType playerID)
{
	DeleteApply(playerID);	//删除一下申请列表
	DelUser(GROUP_FRIEND, playerID); //解除好友关系
	DelUser(GROUP_BLACK, playerID); //解除黑名单关系
	DelUser(GROUP_HATE, playerID);
	DeleteRecentList(playerID); //删除一下最近联系人
	DelFriendPhysicalTab(playerID); //删除体力标记
}

uint32_t Relation::GetClosenessLv(CharIDType playerID)
{
	RelationPlayer* pRelationPlayer = _groupList[GROUP_FRIEND].GetUser(playerID);
	if (nullptr == pRelationPlayer)
	{
		return 0;
	}

	return pRelationPlayer->closenessLv;
}

uint32_t Relation::GetCloseness(CharIDType playerID)
{
	RelationPlayer* pRelationPlayer = _groupList[GROUP_FRIEND].GetUser(playerID);
	if (nullptr == pRelationPlayer)
	{
		return 0;
	}

	return pRelationPlayer->closeness;
}

void Relation::AddCloseness(CharIDType playerID, uint32_t type, uint32_t value)
{
	if (type <= RELATION_CLOSENESS_NONE || type > RELATION_CLOSENESS_JOIN_TEAM)
	{
		return;
	}

	RelationPlayer* pRelationPlayer = _groupList[GROUP_FRIEND].GetUser(playerID);
	if (nullptr != pRelationPlayer)
	{
		//判断是否要重置
		uint32_t nowTime = Time::Now().sec();
		if (Time::GetLocalDayDifference(pRelationPlayer->updateTime, nowTime))
		{
			pRelationPlayer->passDuplicateClonseness = 0;
			pRelationPlayer->killMonsterClonseness = 0;
		}

		if (type == RELATION_CLOSENESS_PASS_DUP)
		{
			/*if (pRelationPlayer->passDuplicateClonseness >= RELATION_PASS_DUP_CLOSENESS_LIMIT)
			{
				return;
			}*/
			//pRelationPlayer->passDuplicateClonseness++;
			//pRelationPlayer->closeness++;
			//说明 每通关一次副本加十点亲密度
			pRelationPlayer->passDuplicateClonseness += 10;
			pRelationPlayer->closeness += 10;
		}
		else if (type == RELATION_CLOSENESS_KILL_MONSTER)
		{
			/*if (pRelationPlayer->killMonsterClonseness >= RELATION_KLLL_MONSTER_CLOSENESS_LIMIT)
			{
				return;
			}*/
			//说明 每击杀100只怪才加一点亲密度(实质上pRelationPlayer->killMonsterClonseness记录的是杀怪的数量)
			uint32_t oldIndex = pRelationPlayer->killMonsterClonseness / 100;
			pRelationPlayer->killMonsterClonseness++;
			uint32_t newIndex = pRelationPlayer->killMonsterClonseness / 100;
			if (oldIndex == newIndex)
			{
				return;
			}
			pRelationPlayer->closeness++;
		}
		else if (type == RELATION_CLOSENESS_HANDSEL_ROSE)
		{
			pRelationPlayer->handselRoseClonseness += value;
			pRelationPlayer->closeness += value;
		}

		pRelationPlayer->updateTime = nowTime;

		//获取亲密度等级
		pRelationPlayer->closenessLv = g_GetRelationMgr()->GetConfigClosenessLv(pRelationPlayer->closeness);

		_change = true;
	}
}

bool Relation::InHateList(CharIDType playerID)
{
	RelationTeam groupList = _groupList[GROUP_HATE];
	return groupList.HaveUser(playerID);
}

uint32_t Relation::GetFriendsAdd()
{
	return _friendsAdd;
}

void Relation::AddFriendsAdd()
{
	_friendsAdd++;
	_change = true;
}

void Relation::SetFriendsAdd(uint32_t value)
{
	_friendsAdd = value;
	_change = true;
}

void Relation::AddActive()
{
	_active++;
}

uint32_t Relation::GetActive()
{
	return _active;
}
